/*
 方案二：每一次执行 then 方法，都会返回一个全新的 promise 实例
   let p2 = p1.then(onfulfilled, onrejected)
     + p2的状态和值，和p1没关系，和 onfulfilled/onrejected 中的任意方法执行的细节有关
     + 首先看方法执行是否报错，如果报错了，则 p2 是失败状态，值是报错原因
     + 如果没有报错，再看方法执行的返回值（别名 x）
       + 如果返回的是一个新的 promise 实例
         + x和p2是同一个对象，则 p2 状态是失败的，值是抛出的异常 TypeError: Chaining cycle detected for promise #<Promise>
         + 如果 x 是一个标准的 promise 实例，则 x 的状态和值就是 p2 的状态和值
         + 还需要判断 x 是否是一个对象或者函数（它可能是一个伪promsie实例）
           如果是，则访问 x.then
           + 如果报错了，则让 p2 是失败状态，值就是报错原因
           + 如果 then 是一个函数
             把 then 方法执行，函数中的 this 需要是x 「then.call(x) 或者 x.then()」，并且传递 onfulfilled/onrejected
             ...
           + 如果不是函数，则说明返回的 x 不是promise实例，则 p2 是成功状态，值就是返回值x
       + 如果不是新的实例，则 p2 是成功状态，值就是返回值
 */

/* let p1 = new Promise((resolve, reject) => {
    // resolve(100)
    reject(0)
})
let p2 = p1.then(value => {
    console.log('成功：', value)
    return AAA
}, reason => {
    console.log('失败：', reason)
    return 10
})
let p3 = p2.then(value => {
    console.log('成功：', value)
    return Promise.reject(-1)
}, reason => {
    console.log('失败：', reason)
    return Promise.resolve(1)
})
let p4 = p3.then(value => {
    console.log('成功：', value)
}, reason => {
    console.log('失败：', reason)
})
p4.then(value => {
    console.log('成功：', value)
}, reason => {
    console.log('失败：', reason)
}) */


/* let p1 = new Promise(resolve => {
    resolve(100)
})
let p2 = p1.then(value => {
    console.log('成功：', value) //=> 成功 100
    return Promise.resolve(Promise.reject(-1))
}, reason => {
    console.log('失败：', reason)
})
p2.then(value => {
    console.log('成功：', value)
}, reason => {
    console.log('失败：', reason) //=> 失败 -1
}) */


//==========================
/*
 then 的穿透(顺延)机制
   每一次执行 then 方法的时候，如果需要传递的 onfulfilled/inrejected 并没有传递，则会把上一个实例的状态和值，顺延给下一个实例「就是执行then返回的这个实例」
 */

/*
let p1 = Promise.reject(0)
let p2 = p1.then(
    /!* value => {
        return value
    },
    reason => {
        throw reason
    } *!/
)
p2.then(value => {
    console.log('成功：', value)
}, reason => {
    console.log('失败：', reason)
})
*/

// 平时写代码，then一般只传递 onfulfilled，最后基于 catch 实现失败的处理「而且不论上述哪个环节出现失败，都会走到最后的catch中」
// 如果出现 失败的实例，但是我们没有对失败进行处理，则控制台会抛出红色警告「Uncaught (in promise)」，此警告不影响后续代码执行
/* Promise.resolve(100)
    .then(value => {
        console.log('成功：', value)
        return value / 10
    })
    .then(value => {
        console.log('成功：', value)
        return value / 10
    })
    .then(value => {
        console.log('成功：', value)
        return AAA
    })
    .catch(reason => {
        console.log('失败：', reason)
    }) */

//==========================
/*
 let p = Promise.all/any/race([promise1,promise2,...]) 
   + 创建一个总的promsie实例「别名 p」
   + 总实例的状态和值，取决于 promises（包含多个promise实例的集合）中每个实例的状态和值
     + all方法：每个实例的状态都为成功，总实例的状态才为成功，值是一个数组，按照顺序存储了每个实例成功的值；其中只要有一个实例的状态是失败，则总实例就是失败，值就是此失败实例的值（后续的实例都不处理了）！
     + any方法：只要有一个成功，整体就是成功，值也是成功这一项的值（后续的也不管了）；只有所有实例都失败，总实例才为失败，值是“AggregateError: All promises were rejected”
     + race方法：哪个实例先处理完毕，总实例的状态和值就按照它的来
   + promises集合中的每一项，都必须是promise实例，如果出现一项不是，则默认会把其转换为promise实例「状态是成功的，值是本身」
   + 要求promises这个集合，需要是符合迭代器规范的集合「Symbol.iterator」（平时开发中，我们全部使用数组作为promises集合）
 */

/* let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
    }, 2000)
})
let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(2)
    }, 1000)
})
let p3 = Promise.resolve(3)
let p4 = 4 //->内部把其转换为promise实例 -> Promise.resolve(4)
let p5 = Promise.reject(5) */

/* Promise.all([p1, p2, p3, p4])
    .then(value => {
        console.log('成功：', value) //成功 [1, 2, 3, 4] 
    })
    .catch(reason => {
        console.log('失败：', reason)
    }) */

/* Promise.all([p1, p2, p5, p4])
    .then(value => {
        console.log('成功：', value)
    })
    .catch(reason => {
        console.log('失败：', reason) //失败 5
    }) */

/* Promise.any([p1, p4, p5])
    .then(value => {
        console.log('成功：', value) //成功 4
    })
    .catch(reason => {
        console.log('失败：', reason)
    }) */

/* Promise.any([p5])
    .then(value => {
        console.log('成功：', value)
    })
    .catch(reason => {
        console.log('失败：', reason) //失败 AggregateError: All promises were rejected
    }) */